package com.neutech.service.impl;

import com.neutech.entity.CartItem;
import com.neutech.enumeration.ResultExceptionEnum;
import com.neutech.mapper.CartMapper;
import com.neutech.service.CartService;
import com.neutech.service.ProductService;
import com.neutech.vo.CartItemVO;
import com.neutech.vo.ProductInfoVO;
import com.neutech.vo.ResultVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class CartServiceImpl implements CartService {

    private final CartMapper mapper;
    private final ProductService productService;
    private final RedisTemplate<Object, Object> redisTemplate;

    @Autowired
    public CartServiceImpl(CartMapper mapper, ProductService productService, RedisTemplate<Object, Object> redisTemplate) {
        this.mapper = mapper;
        this.productService = productService;
        this.redisTemplate = redisTemplate;
    }

    //@Scheduled
    public void clearRedis() {

    }

    public void saveData(int userId) {

    }

    public void loadData(int userId) {
        List<CartItem> cartItems = mapper.selectAllByUserId(userId);
        BoundHashOperations<Object, Object, Object> bho = redisTemplate.boundHashOps(userId);
        bho.put("last_login_time", new Date());
        for (CartItem item : cartItems) {
            bho.put(item.getProductId(), item);
        }
    }

    @Override
    public ResultVO<CartItemVO> addItem(int userId, int productId, int quantity) {
        BoundHashOperations<Object, Object, Object> bho = getBHO(userId);

        if ((Boolean.TRUE.equals(bho.hasKey(productId))))
            return ResultVO.error(ResultExceptionEnum.DATA_ALREADY_EXIST);

        CartItem cartItem = new CartItem();
        cartItem.setUserId(userId);
        cartItem.setProductId(productId);
        cartItem.setQuantity(quantity);
        cartItem.setCreateTime(new Date());
        cartItem.setChecked((byte) 1); // 默认选中

        bho.put(productId, cartItem);
        return ResultVO.success(parseItemToVO(cartItem));
    }

    @Override
    public ResultVO<Void> deleteItem(int userId, int productId) {
        BoundHashOperations<Object, Object, Object> bho = getBHO(userId);

        bho.delete(productId);
        return ResultVO.success();
    }

    @Override
    public ResultVO<Void> deleteItems(int userId, List<Integer> productIdList) {
        BoundHashOperations<Object, Object, Object> bho = getBHO(userId);

        Integer[] productIdArray = productIdList.toArray(new Integer[0]);
        bho.delete((Object[]) productIdArray);
        return ResultVO.success();
    }

    public ResultVO<List<CartItemVO>> selectAllItem(int userId) {
        BoundHashOperations<Object, Object, Object> bho = getBHO(userId);
        bho.delete("last_login_time");

        List<Object> itemObjectList = bho.values();

        if (itemObjectList == null) return ResultVO.error(ResultExceptionEnum.UNKNOWN_ERROR_OCCURED);

        List<CartItemVO> voList = new ArrayList<>();

        for (Object itemObject : itemObjectList) {
            CartItemVO cartItemVO = parseItemToVO((CartItem) itemObject);
            voList.add(cartItemVO);
        }

        bho.put("last_login_time", new Date());

        return ResultVO.success(voList);
    }

    @Override
    public ResultVO<CartItemVO> updateItem(int userId, int productId, int quantity, int checked) {
        if (quantity <= 0 || checked < 0 ||checked > 1)
            return ResultVO.error(ResultExceptionEnum.FORMAT_EXCEPTION);

        BoundHashOperations<Object, Object, Object> bho = getBHO(userId);

        if ((Boolean.FALSE.equals(bho.hasKey(productId))))
            return ResultVO.error(ResultExceptionEnum.DATA_NON_EXIST);

        CartItem cartItem = (CartItem) bho.get(productId);

        if (cartItem == null)
            return ResultVO.error(ResultExceptionEnum.UNKNOWN_ERROR_OCCURED);


        cartItem.setQuantity(quantity);
        cartItem.setChecked((byte) checked);

        bho.put(productId, cartItem);

        return ResultVO.success(parseItemToVO(cartItem));
    }

    private CartItemVO parseItemToVO(CartItem cartItem) {
        ResultVO<ProductInfoVO> pResultVO = productService.selectProductInfoById(cartItem.getProductId());
        ProductInfoVO infoVO = pResultVO.getData();

        if (pResultVO.getCode() != 0 || infoVO == null)
            return null;

        CartItemVO cartItemVO = new CartItemVO();
        cartItemVO.setProductId(cartItem.getProductId());
        cartItemVO.setProductName(infoVO.getName());
        cartItemVO.setProductImage(infoVO.getMainImage());
        cartItemVO.setUnitPrice(infoVO.getPrice());
        cartItemVO.setQuantity(cartItem.getQuantity());
        cartItemVO.setChecked(cartItem.getChecked());
        cartItemVO.setCreateTime(cartItem.getCreateTime());

        return cartItemVO;
    }

    private BoundHashOperations<Object, Object, Object> getBHO(int userId) {
        if (Boolean.FALSE.equals(redisTemplate.hasKey(userId)))
            loadData(userId);

        return redisTemplate.boundHashOps(userId);
    }
}
